// LemCoop
// Copyright (C) 2013  Oliver Naumann <bldrax@gmail.com>

// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

#ifndef LEMC_ANIMATION_H
#define LEMC_ANIMATION_H

#include "WindowsIncludes.h"
#include <allegro5/allegro.h>

#include <string>
#include <vector>

//DEBUG
#include <iostream>

#include "../resourcemanager/allegro_bitmap_manager.h"
#include "../system/screen.h"

/*
* A class for animations. An animation is an array of (allegro_)bitmaps. It has a fixed size and a certain number of
* elements. Each element is shown for a certain amount of ticks. An animation doesn't update itself, instead any object
* that has an animation can tick and reset it. Note that an animation can be as long as it wants in x-direction but it
* can never jump "lines" in the source bitmap - each element of the animation must therefore always have the same
* y-position in the source bitmap.
*/
class Animation
{
private:
	// The id of the source bitmap where the animation is stored.
	std::string m_bitmap;

	// The x-size of every element of the animation.
	int m_size_x;

	// The y-size of every element of the animation.
	int m_size_y;

	// The x-position in the source bitmap of the first element of the animation. 
	int m_bitmap_x;

	// The y-position in the source bitmap of every element of the animation. 
	int m_bitmap_y;

	// The number of elements of this animation.
	unsigned m_number_of_elements;

	// An animation has ended exactly when it was ticked on the last tick of the last element and therefore the
	// current element jumps back to zero. One tick later, m_animation_ended is false again.
	bool m_animation_ended;

	// Stores the times for each element. m_time[0] stores the standard time for elements.
	std::vector<float> m_time;

	// The number of ticks that have already passed since the current element is shown.
	float m_current_ticks;

	// The current element of the animation.
	unsigned m_current_element;

	/*
	* Gets the right x and y coordinates for the current element in the source image.
	*
	* @param x The place where the x coordinate is stored.
	* @param y The place where the y coordinate is stored.
	*
	* @return True if the position could be obtained, false else.
	*/
	bool GetXYFromCurrentElementNumber(int &x, int &y);

public:
	/*
	* Constructs an animation with a single time-value.
	*
	* @param bitmap The identifier of the bitmap that stores the animation.
	* @param size_x The width of the animation elements.
	* @param size_y The height of the animation elements.
	* @param bitmap_x The x-coordinate of the first element of the animation in the bitmap.
	* @param bitmap_y The y-coordinate of the elements of the animation in the bitmap.
	* @param number_of_elements The number of elements that this animation consists of.
	* @param time The time value. Either this is the standard value for every element or (if more time values are
	* added later) it is the time value for only the first element of the animation.
	*/
	Animation(std::string bitmap, unsigned size_x, unsigned size_y, unsigned bitmap_x,
		unsigned bitmap_y, unsigned number_of_elements, float time);

	/*
	* Adds the next time value. It is simply appended to the list of time values. Later changes of the order are
	* not intended.
	*
	* @param time The time value to be inserted.
	*/
	void AddTime(float time);

	/*
	* Resets the current animation. This will set the animation back to the first element with zero ticks passed.
	*/
	void Reset();

	/*
	* Updates the animation.
	*/
	void Update(float timing_factor);

	/*
	* Draws the animation to the screen with given parameters.
	*
	* @param x The x position on the screen to draw the animation element to.
	* @param y The y position on the screen to draw the animation element to.
	* @param scale_x The x scaling for the animation element, standard is 1.0f (no scaling).
	* @param scale_y The y scaling for the animation element, standard is 1.0f (no scaling).
	* @param opacity The opacity to draw the animation element with, standard is 1.0f (full opacity).
	*/
	void Draw(int x, int y, float scale_x = 1.0f, float scale_y = 1.0f, float opacity = 1.0f);

	bool animation_ended() { return m_animation_ended; }
};

#endif